#include "ThreadPool.h"

#include <cassert>
#include <cstdio>

#include "../log/Logging.h"

ThreadPool::ThreadPool(string nameArg)
        : mutex_(),
          notEmpty_(mutex_),
          notFull_(mutex_),
          name_(std::move(nameArg)),
          maxQueueSize_(0),
          running_(false) {
}

ThreadPool::~ThreadPool() {
    if (running_) {
        stop();
    }
}

void ThreadPool::start(int numThreads) {
    assert(threads_.empty());
    running_ = true;
    threads_.reserve(numThreads);
    // 设置线程池容量大小
    for (int i = 0; i < numThreads; ++i) {
        char id[32];
        snprintf(id, sizeof id, "%d", i + 1);
        threads_.emplace_back(new Thread(
                std::bind(&ThreadPool::runInThread, this), name_ + id));
        threads_[i]->start();
    }
    if (numThreads == 0 && threadInitCallback_) {
        threadInitCallback_();
    }
}

void ThreadPool::stop() {
    {
        MutexLockGuard lock(mutex_);
        running_ = false;
        notEmpty_.notifyAll();
        notFull_.notifyAll();
    }
    for (auto &thr : threads_) {
        thr->join();
    }
}

size_t ThreadPool::queueSize() const {
    MutexLockGuard lock(mutex_);
    return queue_.size();
}

void ThreadPool::run(Task task) {
    if (threads_.empty()) {
        task();
    } else {
        MutexLockGuard lock(mutex_);
        while (isFull() && running_) {
            notFull_.wait();
            // 如果当前的任务池满了就回一直一直等待, 直到任务不为空
        }
        if (!running_) return;
        assert(!isFull());
        queue_.push_back(std::move(task));
        notEmpty_.notify();
    }
}

/**
 * 用于获取任务队列中的任务用的, 如果任务队列中没有任务, 或是当前线程池还没有开启就进入等待状态
 * @return
 */
ThreadPool::Task ThreadPool::take() {
    MutexLockGuard lock(mutex_);
    // always use a while-loop, due to spurious wakeup
    while (queue_.empty() && running_) {
        // 如果当前任务队列为空, 就会调用notEmpty等待有任务的时候被唤醒
        notEmpty_.wait();
    }
    Task task;
    if (!queue_.empty()) {
        task = queue_.front();
        queue_.pop_front();
        if (maxQueueSize_ > 0) {
            notFull_.notify();
        }
    }
    return task;
}

bool ThreadPool::isFull() const {
    mutex_.assertLocked();
    return maxQueueSize_ > 0 && queue_.size() >= maxQueueSize_;
}

/**
 * 在对应线程中运行的任务, 如果当前线程在运行中的话就从任务队列头取出任务来运行
 */
void ThreadPool::runInThread() {
    try {
        if (threadInitCallback_) {
            threadInitCallback_();
        }
        while (running_) {
            Task task(take());
            if (task) task();
            // 获取任务, 如果任务不为空就执行

        }
    }
/*    catch (const Exception &ex) {
        fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
        fprintf(stderr, "reason: %s\n", ex.what());
        fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
        abort();
    }*/
    catch (const std::exception &ex) {
        /*fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
        fprintf(stderr, "reason: %s\n", ex.what());
        abort();*/
        LOG_FATAL << "异常原因导致ThreadPoll : " << name_ << " 创建失败, 失败原因 : " << ex.what();
    }
    catch (...) {
        fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str());
        throw; // rethrow
    }
}
